package com.jml.spring.aop注解事务.aop;

import com.jml.spring.aop注解事务.TransactionUtils.TransactionUtils;
import com.jml.spring.aop注解事务.annotation.ExtTransational;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Aspect
@Component
public class AopExtTransaction {


	@Autowired
	private TransactionUtils transactionUtils;

	// 异常通知
	@AfterThrowing("execution(* com.jml.spring.aop注解事务.service.*.*.*(..))")
	public void afterThrowing() {
		System.out.println("注解事务 异常通知回滚事务....");
		//获取方法上的注解
		transactionUtils.rollback();
//*
//获取当前线程事务
		TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
		//回滚当前事务
		transactionStatus.setRollbackOnly();

	}

	// 环绕通知   在方法前后执行
	@Around("execution(* com.jml.spring.aop注解事务.service.*.*.*(..))")
	public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		//获取方法上的注解
		ExtTransational extTransational = getMethodExtTransational(proceedingJoinPoint);
		TransactionStatus transactionStatus = null;
		transactionStatus = begin(transactionStatus, extTransational);
		//4.调用目标代理对象
		proceedingJoinPoint.proceed();
		commit(transactionStatus);
	}

	private void commit(TransactionStatus transactionStatus) {
		System.out.println("提交事务!");
		//5.判断该方法上是否加了注解,如果存在注解，提交事务
		if(transactionStatus!=null){
			//3.如果存在事务注解，开启事务
			transactionUtils.commit(transactionStatus);
		}
	}

	public TransactionStatus begin(TransactionStatus transactionStatus,ExtTransational extTransational) {
		System.out.println("开启事务!");
		if(extTransational==null){
			return null;
		}
		//3.如果存在事务注解，开启事务
		return transactionUtils.begin();
	}

	//获取方法注解
	public ExtTransational getMethodExtTransational(ProceedingJoinPoint proceedingJoinPoint)
			throws NoSuchMethodException {
		//1.获取代理对象的方法
		String methodName = proceedingJoinPoint.getSignature().getName();
		Class<?> classTarget = proceedingJoinPoint.getTarget().getClass();
		//获取目标对象类型
		Class[] par = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes();
		//2.获取方法上是否加了注解
		Method objMethod = classTarget.getMethod(methodName, par);
		ExtTransational extTransational = objMethod.getDeclaredAnnotation(ExtTransational.class);
		return extTransational;

	}

}
